package com.ttg.web.service.job;

import com.google.common.util.concurrent.ListenableFuture;
import com.ttg.common.dto.TaskBaseDTO;
import com.ttg.common.dto.TaskCostGradingDTO;
import com.ttg.common.enums.AccountDimTypeEnum;
import com.ttg.common.enums.AcctSubjectTypeEnum;
import com.ttg.common.enums.IntervalTypeEnum;
import com.ttg.common.exception.BaseException;
import com.ttg.common.utils.AmountGenerator;
import com.ttg.common.utils.DateTimeUtil;
import com.ttg.common.utils.IntegerUtil;
import com.ttg.common.utils.RandomInt;
import com.ttg.common.vo.TaskResultVO;
import com.ttg.model.po.AccountInfoPO;
import com.ttg.model.po.IndustryPO;
import com.ttg.model.pojo.BankOrderCreditInfoPrimitive;
import com.ttg.model.vo.MerchTradeInfoByMonthVO;
import com.ttg.model.pojo.BankAccountPrimitive;
import com.ttg.model.pojo.BankPublicMerchTradePrimitive;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * Description：
 * Author: chenyou
 * Date: 2025/9/2 15:13
 * Company: ttg
 * Copyright: Copyright (c) 2025
 */
public class JobCommon {

    public static TaskBaseDTO getCheckYearAndMonth(TaskBaseDTO dto){
        LocalDate lastMonth = LocalDate.now().minusMonths(1);
        String year = DateTimeUtil.getYear(lastMonth);
        String month = DateTimeUtil.getMonth(lastMonth);
        //默认按月类型执行任务
        if(StringUtils.isBlank(dto.getIntervalType())){
            dto.setIntervalType(IntervalTypeEnum.月度区间.getValue());
        }
        if(IntervalTypeEnum.月度区间.getValue().equals(dto.getIntervalType())){
            //未传年月,返回上一月
            if (Objects.isNull(dto) || StringUtils.isBlank(dto.getYear()) || StringUtils.isBlank(dto.getMonth())) {
                dto.setDate(DateTimeUtil.formatYYYYMM(lastMonth));
                return dto;
            }else{
                Integer yearInt = Integer.valueOf(year);
                Integer monthInt = Integer.valueOf(month);
                //传入年份大于上月年份,返回当年上一月
                if(IntegerUtil.gt(Integer.valueOf(dto.getYear()),yearInt)){
                    dto.setDate(DateTimeUtil.formatYYYYMM(lastMonth));
                    return dto;
                }
                //传入月份大于上月,返回当年上一月
                if(IntegerUtil.gt(Integer.valueOf(dto.getMonth()),monthInt)){
                    dto.setDate(DateTimeUtil.formatYYYYMM(lastMonth));
                    return dto;
                }
                //否则返回传入年月
                return dto;
            }
        }else{
            //未传年
            if (Objects.isNull(dto) || StringUtils.isBlank(dto.getYear())){
                dto.setDate(DateTimeUtil.formatYYYY(lastMonth));
                return dto;
            }else{
                Integer yearInt = Integer.valueOf(year);
                //传入年份大于上月年份,返回上月年份
                if(IntegerUtil.gt(Integer.valueOf(dto.getYear()),yearInt)){
                    dto.setDate(DateTimeUtil.formatYYYY(lastMonth));
                    return dto;
                }
                return dto;
            }
        }

    }

    public static TaskCostGradingDTO getCheckDate(TaskCostGradingDTO dto){
        LocalDate lastMonth = LocalDate.now().minusMonths(1);
        String year = DateTimeUtil.getYear(lastMonth);
        String month = DateTimeUtil.getMonth(lastMonth);
        //默认按月类型执行任务
        if(StringUtils.isBlank(dto.getIntervalType())){
            dto.setIntervalType(IntervalTypeEnum.月度区间.getValue());
        }
        //未传年月,返回上一月
        if (Objects.isNull(dto) || StringUtils.isBlank(dto.getYear()) || StringUtils.isBlank(dto.getMonth())) {
            dto.setDate(DateTimeUtil.formatYYYYMM(lastMonth));
            return dto;
        }else{
            Integer yearInt = Integer.valueOf(year);
            Integer monthInt = Integer.valueOf(month);
            //传入年份大于上月年份,返回当年上一月
            if(IntegerUtil.gt(Integer.valueOf(dto.getYear()),yearInt)){
                dto.setDate(DateTimeUtil.formatYYYYMM(lastMonth));
                return dto;
            }
            //传入月份大于上月,返回当年上一月
            if(IntegerUtil.gt(Integer.valueOf(dto.getMonth()),monthInt)){
                dto.setDate(DateTimeUtil.formatYYYYMM(lastMonth));
                return dto;
            }
            //否则返回传入年月
            return dto;
        }

    }

    /**
     * 处理任务结果
     * @param results
     * @param futures
     * @param isJuc
     * @return: com.ttg.common.vo.TaskResultVO
     * @date: 2025/9/15 15:13
     * @author: chenyou
     */
    public TaskResultVO taskResult(List<TaskResultVO> results, List<ListenableFuture<TaskResultVO>> futures, boolean isJuc){
        TaskResultVO resultVO;
        if(isJuc){
            results = futures.stream().map(o -> {
                try {
                    return o.get();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
                return null;
            }).collect(Collectors.toList());
        }
        if(CollectionUtils.isEmpty(results)){
            resultVO = taskReuslt(Status.FAIL.getValue(),false,"任务执行结果为空");
        }
        //任务执行结果
        if(results.stream().anyMatch(o -> !o.getStatus().equals(Status.SUCCESS.getValue()))){
            resultVO = results.stream().filter(o -> !o.getStatus().equals(Status.SUCCESS.getValue())).findFirst().get();
            throw new BaseException(resultVO.getRemark());
        }else {
            resultVO = taskReuslt(Status.SUCCESS.getValue(),false,"ok");
        }
        return resultVO;
    }

    public static TaskResultVO taskReuslt(Integer status, boolean warn, String remark){
        return new TaskResultVO(status,LocalDate.now(),warn,remark);
    }

    @AllArgsConstructor
    @Getter
    public enum Status{

        SUCCESS(1,"成功"),
        FAIL(4,"失败"),
        PROCESS(9,"执行中");

        private Integer value;
        private String msg;

    }






    /********************** 临时测试数据 ***********************/

    public List<IndustryPO> getTestIndustry(){
        IndustryPO c1 = new IndustryPO();
        c1.setClsId1("01");
        c1.setCls1Name("美食");
        c1.setClsId2("011");
        c1.setCls2Name("粤菜");

        IndustryPO c2 = new IndustryPO();
        c2.setClsId1("01");
        c2.setCls1Name("美食");
        c2.setClsId2("012");
        c2.setCls2Name("湘菜");

        return Arrays.asList(c1,c2);
    }

    public static List<MerchTradeInfoByMonthVO> getMerchList(){
        MerchTradeInfoByMonthVO m1 = new MerchTradeInfoByMonthVO();
        m1.setMctNo("86000000");
        m1.setMctName("测试商户0");
        m1.setMctCustNo("6000000");
        m1.setAvgDepositAmount(new BigDecimal(100000));
        m1.setCreditFlag("1");
        m1.setUseCreditFlag("1");
        m1.setClsId1("1");
        m1.setClsId2("11");

        MerchTradeInfoByMonthVO m2 = new MerchTradeInfoByMonthVO();
        m2.setMctNo("86000001");
        m2.setMctName("测试商户1");
        m2.setMctCustNo("6000001");
        m2.setAvgDepositAmount(new BigDecimal(200000));
        m2.setCreditFlag("1");
        m2.setUseCreditFlag("1");
        m2.setClsId1("1");
        m2.setClsId2("11");

        MerchTradeInfoByMonthVO m3 = new MerchTradeInfoByMonthVO();
        m3.setMctNo("86000002");
        m3.setMctName("测试商户2");
        m3.setMctCustNo("6000002");
        m3.setAvgDepositAmount(new BigDecimal(300000));
        m3.setCreditFlag("0");
        m3.setUseCreditFlag("0");
        m3.setClsId1("1");
        m3.setClsId2("12");

        return Arrays.asList(m1,m2,m3);
    }

    public List<AccountInfoPO> getBindAcctList(){
        List<AccountInfoPO> list = new ArrayList<>();
        AccountInfoPO a0 = new AccountInfoPO();
        a0.setActNo(10000000L);
        a0.setActName("直绑账号0");
        a0.setActMctNo(86000000L);
        a0.setAvgDepositAmount(new BigDecimal(10000000));
        list.add(a0);
        AccountInfoPO a1 = new AccountInfoPO();
        a1.setActNo(10000000L);
        a1.setActName("直绑账号1");
        a1.setActMctNo(86000001L);
        a1.setAvgDepositAmount(new BigDecimal(10000000));
        list.add(a1);
        AccountInfoPO a2 = new AccountInfoPO();
        a2.setActNo(10000001L);
        a2.setActName("其他账号2");
        a2.setActMctNo(86000002L);
        a2.setAvgDepositAmount(new BigDecimal(10000000));
        list.add(a2);
        return list;
    }

    public List<AccountInfoPO> getAllAcctList(){
        List<AccountInfoPO> list = new ArrayList<>();
        AccountInfoPO a0 = new AccountInfoPO();
        a0.setActNo(10000000L);
        a0.setActName("全量账号0");
        a0.setActMctNo(86000000L);
        a0.setAvgDepositAmount(new BigDecimal(10000000));

        AccountInfoPO a1 = new AccountInfoPO();
        a1.setActNo(10000000L);
        a1.setActName("全量账号1");
        a1.setActMctNo(86000001L);
        a1.setAvgDepositAmount(new BigDecimal(10000000));

        AccountInfoPO a2 = new AccountInfoPO();
        a2.setActNo(10000001L);
        a2.setActName("全量账号1");
        a2.setActMctNo(86000002L);
        a2.setAvgDepositAmount(new BigDecimal(10000000));
        list.add(a0);
        list.add(a1);
        list.add(a2);
        return list;
    }

    public static List<BankAccountPrimitive> testAccountPrimitive(Integer day){
        List<BankAccountPrimitive> list = new ArrayList<>();

        BigDecimal minBal = new BigDecimal(200000);
        BigDecimal maxBal = new BigDecimal(20000000);
        BigDecimal minCrcrdBill = new BigDecimal(300000);
        BigDecimal maxCrcrdBill = new BigDecimal(30000000);
        BigDecimal minCreAmt = new BigDecimal(100000);
        BigDecimal maxCreAmt = new BigDecimal(10000000);
        BigDecimal minUseCreAmt = new BigDecimal(10000);
        BigDecimal maxUseCreAmt = new BigDecimal(1000000);
        BigDecimal minRate = new BigDecimal(0);
        BigDecimal maxRate = new BigDecimal(1);
        for(int i=0;i<10000;i++){
            BankAccountPrimitive primitive = new BankAccountPrimitive();
            primitive.setDataTime(day);
            primitive.setActNo((long) (86740000 + i));
            if(i<10){
                primitive.setMctNo(86000001L);
            }
            if(i>=10&&i<20){
                primitive.setMctNo(86000002L);
            }
            if(i>=20&&i<30){
                primitive.setMctNo(86000003L);
            }
            if(i>=30) {
                primitive.setMctNo((long) (86000000 + i));
            }
            if(i%2==0){
                primitive.setActSubjectType(AcctSubjectTypeEnum.个人户.getValue());
                primitive.setActType(AccountDimTypeEnum.直绑账户.getValue());
            }else{
                primitive.setActSubjectType(AcctSubjectTypeEnum.对公户.getValue());
                primitive.setActType(AccountDimTypeEnum.其他账户.getValue());
            }
            primitive.setTimeAmt(AmountGenerator.generateBigDecimal(minBal,maxBal,0));
            primitive.setCrCrdBillAmt(AmountGenerator.generateBigDecimal(minCrcrdBill,maxCrcrdBill,0));
            if(i%2==0){
                primitive.setCreditFlag(1);
            }else{
                primitive.setCreditFlag(0);
            }
            primitive.setCreditAmt(AmountGenerator.generateBigDecimal(minCreAmt,maxCreAmt,0));
            if(i%4==0){
                primitive.setUseCreditFlag(1);
            }else{
                primitive.setUseCreditFlag(0);
            }
            primitive.setUseCreditAmt(AmountGenerator.generateBigDecimal(minUseCreAmt,maxUseCreAmt,0));
            primitive.setDepositRate(AmountGenerator.generateBigDecimal(minRate,maxRate,2));
            primitive.setCreditRate(AmountGenerator.generateBigDecimal(minRate,maxRate,2));
            list.add(primitive);
        }
        return list;
    }

    public static List<BankPublicMerchTradePrimitive> testMerchPrimitives(Integer day){
        List<BankPublicMerchTradePrimitive> list = new ArrayList<>();
        BigDecimal minTradeAmt = new BigDecimal(10000);
        BigDecimal maxTradeAmt = new BigDecimal(1000000);
        BigDecimal minTimeAmt = new BigDecimal(100000);
        BigDecimal maxTimeAmt = new BigDecimal(10000000);
        BigDecimal minFee = new BigDecimal(100);
        BigDecimal maxFee = new BigDecimal(10000);
        BigDecimal minRepair = new BigDecimal(200);
        BigDecimal maxRepair = new BigDecimal(20000);
        BigDecimal minBal = new BigDecimal(200000);
        BigDecimal maxBal = new BigDecimal(20000000);
        BigDecimal minCreditAmt = new BigDecimal(3000);
        BigDecimal maxCreditAmt = new BigDecimal(300000);
        for(int i=0;i<10000;i++){
            BankPublicMerchTradePrimitive primitive = new BankPublicMerchTradePrimitive();
            primitive.setDataTime(day);
            primitive.setMctNo(String.valueOf(86000000 + i));
            primitive.setAgentNo(86000081L);
            primitive.setOrgNo(86000091L);
            if(i%3==0){
                primitive.setLivenessDayFlag(0);
            }else {
                primitive.setLivenessDayFlag(1);
            }

            primitive.setTradeAmt(AmountGenerator.generateBigDecimal(minTradeAmt,maxTradeAmt,0));
            primitive.setTradeCount(RandomInt.nextInt1To1000());
            primitive.setTimeAmt(AmountGenerator.generateBigDecimal(minTimeAmt,maxTimeAmt,0));
            primitive.setFeeAmt(AmountGenerator.generateBigDecimal(minFee,maxFee,0));
            primitive.setRepairAmt(AmountGenerator.generateBigDecimal(minRepair,maxRepair,0));
//            primitive.setBalAmt(AmountGenerator.generateBigDecimal(minBal,maxBal,0));
            primitive.setCreditTradeAmt(AmountGenerator.generateBigDecimal(minCreditAmt,maxCreditAmt,0));
            if(i%3==0){
                primitive.setClsId1("01");
                primitive.setClsId2("011");
                primitive.setClsId3("01101");
            }else if(i%3==1){
                primitive.setClsId1("01");
                primitive.setClsId2("012");
                primitive.setClsId3("01201");
            }else if(i%3==2){
                primitive.setClsId1("01");
                primitive.setClsId2("013");
                primitive.setClsId3("01301");
            }

            list.add(primitive);
        }
        return list;
    }

    public static List<BankPublicMerchTradePrimitive> getAllMerchTradePrimitive(int date){
        List<BankPublicMerchTradePrimitive> list = new ArrayList<>();
        BankPublicMerchTradePrimitive p1 = new BankPublicMerchTradePrimitive();
        p1.setDataTime(date);
        p1.setMctNo("86000000");
        p1.setLivenessDayFlag(1);
        p1.setTradeAmt(new BigDecimal(100000));
        p1.setTimeAmt(new BigDecimal(1000));
        p1.setFeeAmt(new BigDecimal(250));
        p1.setRepairAmt(new BigDecimal(500));
        p1.setCreditTradeAmt(new BigDecimal(80000));
        p1.setAgentNo(86000081L);
        p1.setOrgNo(86000091L);
        p1.setClsId1("01");
        p1.setClsId2("011");
        p1.setClsId3("01101");

        BankPublicMerchTradePrimitive p2 = new BankPublicMerchTradePrimitive();
        p2.setDataTime(date);
        p2.setMctNo("86000001");
        p2.setLivenessDayFlag(0);
        p2.setTradeAmt(new BigDecimal(200000));
        p2.setTimeAmt(new BigDecimal(2000));
        p2.setFeeAmt(new BigDecimal(500));
        p2.setRepairAmt(new BigDecimal(1000));
        p2.setCreditTradeAmt(new BigDecimal(160000));
        p2.setAgentNo(86000081L);
        p2.setOrgNo(86000091L);
        p2.setClsId1("01");
        p2.setClsId2("011");
        p2.setClsId3("01101");

        BankPublicMerchTradePrimitive p3 = new BankPublicMerchTradePrimitive();
        p3.setDataTime(date);
        p3.setMctNo("86000002");
        p3.setLivenessDayFlag(1);
        p3.setTradeAmt(new BigDecimal(400000));
        p3.setTimeAmt(new BigDecimal(4000));
        p3.setFeeAmt(new BigDecimal(1000));
        p3.setRepairAmt(new BigDecimal(2000));
        p3.setCreditTradeAmt(new BigDecimal(320000));
        p3.setAgentNo(86000081L);
        p3.setOrgNo(86000091L);
        p3.setClsId1("01");
        p3.setClsId2("011");
        p3.setClsId3("01101");

        BankPublicMerchTradePrimitive p4 = new BankPublicMerchTradePrimitive();
        p4.setDataTime(date);
        p4.setMctNo("86000003");
        p4.setLivenessDayFlag(0);
        p4.setTradeAmt(new BigDecimal(1000000));
        p4.setTimeAmt(new BigDecimal(10000));
        p4.setFeeAmt(new BigDecimal(1000));
        p4.setRepairAmt(new BigDecimal(2000));
        p4.setCreditTradeAmt(new BigDecimal(320000));
        p4.setAgentNo(86000082L);
        p4.setOrgNo(86000091L);
        p4.setClsId1("01");
        p4.setClsId2("012");
        p4.setClsId3("01201");

        BankPublicMerchTradePrimitive p5 = new BankPublicMerchTradePrimitive();
        p5.setDataTime(date);
        p5.setMctNo("86000004");
        p5.setLivenessDayFlag(1);
        p5.setTradeAmt(new BigDecimal(2000000));
        p5.setTimeAmt(new BigDecimal(10000));
        p5.setFeeAmt(new BigDecimal(2000));
        p5.setRepairAmt(new BigDecimal(4000));
        p5.setCreditTradeAmt(new BigDecimal(320000));
        p5.setAgentNo(86000082L);
        p5.setOrgNo(86000091L);
        p5.setClsId1("01");
        p5.setClsId2("012");
        p5.setClsId3("01201");

        BankPublicMerchTradePrimitive p6 = new BankPublicMerchTradePrimitive();
        p6.setDataTime(date);
        p6.setMctNo("86000005");
        p6.setLivenessDayFlag(0);
        p6.setTradeAmt(new BigDecimal(3000000));
        p6.setTimeAmt(new BigDecimal(10000));
        p6.setFeeAmt(new BigDecimal(4000));
        p6.setRepairAmt(new BigDecimal(8000));
        p6.setCreditTradeAmt(new BigDecimal(320000));
        p6.setAgentNo(86000082L);
        p6.setOrgNo(86000091L);
        p6.setClsId1("01");
        p6.setClsId2("012");
        p6.setClsId3("01201");

        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);
        list.add(p5);
        list.add(p6);
        return list;
    }

    public static List<BankOrderCreditInfoPrimitive> getOrderCreditInfoList(LocalDateTime day){
        List<BankOrderCreditInfoPrimitive> list = new ArrayList<>();
        for(int i=0;i<10000;i++){
            BankOrderCreditInfoPrimitive info = new BankOrderCreditInfoPrimitive();
            info.setOrdNo(String.valueOf(86000000 + i));
            info.setOpenid("dsadsfsffdfree");
            info.setTradeType(1);
            info.setTradeTime(day);
            if(i%3==0){
                info.setMctNo(86000000);
                info.setMctName("测试商户");

            }else if(i%3==1){
                info.setMctNo(86000001);
                info.setMctName("测试商户1");
            }else{
                info.setMctNo(86000002);
                info.setMctName("测试商户2");
            }
            info.setManageUserName("管护人");
            info.setAgentName("机构啊啊啊");

            list.add(info);
        }

        return list;
    }
}
